package pers.mor.tomcat.config;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import pers.mor.tomcat.catalina.*;
import pers.mor.tomcat.http.Constant;

import java.util.Iterator;
import java.util.List;
import java.util.Map;

public class ServerXML {

    public static void builderServer(Server server) {
        try {
            Document doc = new SAXReader().read(Constant.serverXmlFile);
            Element serve = doc.getRootElement();
            Iterator<Element> it = serve.elementIterator("Service");
            while (it.hasNext()) {
                Element element = it.next();
                String name = element.attributeValue("name");
                Engine engine = buildEngine(element);
                Service service = new Service(name, engine);
                buildConnectors(element, service);
                server.getServiceList().add(service);
            }
        } catch (DocumentException e) {
            e.printStackTrace();
        }
    }

    private static void buildConnectors(Element element, Service service) {
        List<Element> list = element.elements("Connector");
        for (Element e : list) {
            String port = e.attributeValue("port");
            String protocol = e.attributeValue("protocol");
            Connector connector = new Connector(Integer.parseInt(port), protocol);
            compressionConfig(e, connector);
            service.getConnectorList().add(connector);
            service.getPortList().add(Integer.valueOf(port));
        }
    }

    private static void compressionConfig(Element e, Connector connector) {
        String compression = e.attributeValue("compression");
        String compressionMinSize = e.attributeValue("compressionMinSize");
        String noCompressionUserAgents = e.attributeValue("noCompressionUserAgents");
        String compressableMimeType = e.attributeValue("compressableMimeType");

        boolean flag = check(new String[]{compression, compressionMinSize, noCompressionUserAgents, compressableMimeType});
        if (flag == false) {
            return;
        }

        connector.compression().setCompression(compression);
        connector.compression().setCompressionMinSize(Integer.valueOf(compressionMinSize));
        connector.compression().setNoCompressionUserAgents(noCompressionUserAgents);
        connector.compression().setCompressableMimeType(compressableMimeType);
    }

    private static boolean check(String[] strings) {
        for (String string : strings) {
            if (string == null || string.trim().equals("")) {
                return false;
            }
        }
        return true;
    }

    public static Engine buildEngine(Element service) {
        Iterator<Element> it = service.elementIterator("Engine");
        Element element = it.next();
        String name = element.attributeValue("name");
        String defaultHost = element.attributeValue("defaultHost");
        Engine engine = new Engine(name, defaultHost);
        buildHosts(element, engine.getHostMap());
        return engine;
    }

    private static void buildHosts(Element engine, Map<String, Host> hostMap) {
        Iterator<Element> it = engine.elementIterator("Host");
        while (it.hasNext()) {
            Element element = it.next();
            String name = element.attributeValue("name");
            String appBase = element.attributeValue("appBase");
            String reloadable = element.attributeValue("reloadable");
            String dynamicDeploy = element.attributeValue("dynamicDeploy");
            boolean reload = Boolean.parseBoolean(reloadable);
            boolean dynamic = Boolean.parseBoolean(dynamicDeploy);
            Host host = new Host(name, appBase, reload, dynamic);
            buildContexts(element, host);
            hostMap.put(host.getName(), host);
        }
    }

    private static void buildContexts(Element elementHost, Host host) {
        Iterator<Element> it = elementHost.elementIterator("Context");
        while (it.hasNext()) {
            Element element = it.next();
            String path = element.attributeValue("path");
            String base = element.attributeValue("base");
            String reloadable = element.attributeValue("reloadable");
            Context context = new Context(path, base, host, Boolean.parseBoolean(reloadable));
            host.getContextMap().put(context.getPath(), context);
        }
    }

}
